/*
 Copyright (c) 2008 Computer Engineering and Communication Networks Lab (TIK)
 Swiss Federal Institute of Technology (ETH) Zurich, Switzerland
 All rights reserved.
 Permission is hereby granted, without written agreement and without
 license or royalty fees, to use, copy, modify, and distribute this
 software and its documentation for any purpose, provided that the above
 copyright notice and the following two paragraphs appear in all copies
 of this software.
 IN NO EVENT SHALL THE TIK OR THE ETH ZURICH BE LIABLE TO ANY PARTY
 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 THE TIK OR THE ETH ZURICH HAVE BEEN ADVISED OF THE POSSIBILITY OF
 SUCH DAMAGE.
 THE TIK AND THE ETH ZURICH SPECIFICALLY DISCLAIM ANY WARRANTIES,
 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND TIK AND THE ETH ZURICH
 HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
 ENHANCEMENTS, OR MODIFICATIONS.
 Title: Variator
 Description: Standard variator, can be adapted to generate user-defined variators
 Copyright: Copyright (c) 2008
 Company: ETH Zurich
 */
package ch.ethz.ee.tik.sop.pisalib.variator;

import java.io.BufferedReader;
import java.io.FileReader;

/** Contains the methods which are called in the different states of the <code>StateMachine</code>.
 * It includes two methods for state 0 and state 2, as well as methods for reading the parameter and
 * configuration files.
 * 
 * @author Tamara Ulrich
 * @version 1.0
 */
class States {

	/** Initializes the variator. The parameters are read and tested for reasonability, the population is initialized
	 * and the initial file and the first variator file is written.
	 */
	static void state0(){
		readParam(Variator.population.paramFileName);
		readParam(Variator.population.configFile);
		Variator.population.testParam();
		
		Variator.randomGenerator.setSeed(Variator.population.seed);
		
		Variator.population.initialize();
		Variator.population.writePopulation(Variator.population.initialFile);
		Variator.population.writePopulation(Variator.population.variatorFile);	
		
		Variator.debugPrint("Generation counter set to 1.");
		Variator.population.generation = 1;		
	}
	
	/** The main state of the variator which performs the variation. It cleans the population by removing all individuals
	 * which are not contained in the archive file (which is generated by the selector). Then, it performs recombination and
	 * mutation on the parent individuals given by the selector file (which is also generated by the selector) and writes the offspring
	 * to the variator file.
	 */
	static void state2(){
		Variator.population.generation += 1;
		Variator.population.performClean();
		Variator.debugPrint("Clean of population finished.");
		Variator.population.variate();
		Variator.debugPrint("Variation finished.");
		Variator.population.writePopulation(Variator.population.variatorFile, Variator.population.offspring);
	}
	
	/** Reads the parameters in the given file. Skips over empty lines and lines starting with a <code>#</code>.
	 * 
	 * @param filename the name of the file which contains the parameters
	 */
	private static void readParam(String filename){
		boolean readCorrectly=true;
		try {
			FileReader fr = new FileReader(filename);
			BufferedReader br = new BufferedReader(fr);
			String paramName="", paramValue="";
			String nextParam = br.readLine();
			while (nextParam != null) {
				
				/* continue with next line, if no key found */
				if (nextParam.length() == 0)
				{
					nextParam = br.readLine();
					continue;
				}
				
				/* forget about comments */
				if (nextParam.charAt(0) == '#')
				{
					nextParam = br.readLine();
					continue;
				}
								
				/* read next line, split it and extract name and value */
				String[] str = nextParam.split(" ");
				paramName = str[0];
				paramValue = str[1];
				
				// first, see if the parameter is a fixed parameter of the abstract PopulationAbstract class.
				// If this is not the case, see if it is a user-defined parameter in the Population class.
				if (!Variator.population.setFixedParam(paramName,paramValue)) {
					readCorrectly = readCorrectly && Variator.population.setNonfixedParam(paramName,paramValue);
				}
					
				nextParam = br.readLine();
			}
			br.close();
			fr.close();
		}
		catch (Exception ex) {
			System.err.println("Problem reading the parameter file! Terminating!");
			ex.printStackTrace();
		}
		if (!readCorrectly){
			System.out.println("Could not read parameter file.");
			System.exit(1);
		}


	}
	


}